<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>templates test</title>
		<script src="js/jquery-1.7.2.min.js"></script>
		<script src="js/templates/highcharts.js"></script>
		 
		<script src="../src/tiletemplate.js"></script>
		<script src="js/templates/template-native.js"></script>
		<script src="js/templates/tmpl.js"></script>
		<script src="js/templates/doT.js"></script>
		<script src="js/templates/juicer.js"></script>
		<script src="js/templates/kissy.js"></script>
		<script src="js/templates/template.js"></script>
		<script src="js/templates/mustache.js"></script>
		<script src="js/templates/handlebars.js"></script>
		<script src="js/templates/baiduTemplate.js"></script>
		<script src="js/templates/jquery.tmpl.js"></script>
		<script src="js/templates/easytemplate.js"></script>
		<script src="js/templates/underscore.js"></script>
		<script src="js/templates/etpl.js"></script>

		<script>
		 
		// 数据量
		var length = 100;
		// 渲染次数
		var number = 10000;

		var data = {
			list: []
		};

		for (var i = 0; i < length; i ++) {
			data.list.push({
				index: i,
				user: '<strong style="color:red">糖饼</strong>',
				site: 'http://www.planeart.cn',
				weibo: 'http://weibo.com/planeart',
				QQweibo: 'http://t.qq.com/tangbin'  
			}); 
		};


		// 待测试的引擎列表
		var testList = [

			{
				name: 'tileTemplate',
				tester: function () { 
                    //tileTemplate.set("debug", true);
                    tileTemplate.set("filter", false);
					var source = document.getElementById('tile-test-template').innerHTML;
					var fn = tileTemplate.compile(source, data);
					for (var i = 0; i < number; i ++) {
						fn(data);
					}
				}
			},

			{
				name: 'artTemplate',
				tester: function () {
					//template.config('escape', false);
					var source = document.getElementById('template').innerHTML;
					var fn = template.compile(source);
					for (var i = 0; i < number; i ++) {
						fn(data);
					}
				}
			},
			
			{
				name: 'juicer',
				tester: function () {
					var config = {cache:true};

					var source = document.getElementById('juicer').innerHTML;
					for (var i = 0; i < number; i ++) {
						juicer.to_html(source, data, config);
					}
				}
			},
			
			{
				name: 'doT',
				tester: function () {
					var source = document.getElementById('doT').innerHTML;
					var doTtmpl = doT.template(source);
					for (var i = 0; i < number; i ++) {
						doTtmpl(data);
					}
				}
			},
			
			{
				name: 'Handlebars',
				tester: function () {
					var source = document.getElementById('Handlebars').innerHTML;
					var fn = Handlebars.compile(source);
					for (var i = 0; i < number; i ++) {
						fn(data);
					}
				}
			},

			{
				name: 'etpl',
				tester: function () {
					// dont escape html
					etpl.config({
						defaultFilter: ''
					});
					var source = document.getElementById('etpl').innerHTML;
					var fn = etpl.compile(source);
					for (var i = 0; i < number; i ++) {
						fn(data);
					}
				}
			},
			
			{
				name: 'tmpl',
				tester: function () {
					var source = document.getElementById('tmpl').innerHTML;
					var fn = tmpl(source);
					for (var i = 0; i < number; i ++) {
						fn(data);
					}
				}
			},
			
			{
				name: 'easyTemplate',
				tester: function () {
					var source = document.getElementById('easyTemplate').innerHTML;
					var fn = easyTemplate(source);
					for (var i = 0; i < number; i ++) {
						// easyTemplate 渲染方法被重写到 toString(), 需要取值操作才会运行
						fn(data) + '';
					}
				}
			},

			{
				name: 'underscoreTemplate',
				tester: function () {
					var source = document.getElementById('underscoreTemplate').innerHTML;
					var fn = _.template(source);
					for (var i = 0; i < number; i ++) {
						fn(data);
					}
				}
			},
			
			{
				name: 'baiduTemplate',
				tester: function () {
					var bt=baidu.template;
					bt.ESCAPE = false;
					for (var i = 0; i < number; i ++) {
						bt('baidu-template', data);
					}
				}
			},
			
			 // jqueryTmpl 太慢，可能导致浏览器停止响应
			/*{
				name: 'jqueryTmpl',
				tester: function () {
					var source = document.getElementById("jqueryTmpl").innerHTML;
					for (var i = 0; i < number; i ++) {
						$.tmpl(source, data);
					}
				}
			},*/
			
			{
				name: 'Mustache',
				tester: function () {
					var source = document.getElementById('Mustache').innerHTML;
					for (var i = 0; i < number; i ++) {
						Mustache.to_html(source, data);
					}
				}
			}
			
		];

		KISSY.use('template',function(S,T) {
			testList.push({
				name: 'kissyTemplate',
				tester: function () {
					var source= document.getElementById('kissy').innerHTML;

					for (var i = 0; i < number; i ++) {
						T(source).render(data);
					}
				}
			});
		});


		var startTest = function () {

			var Timer = function (){
				this.startTime = + new Date;
			};

			Timer.prototype.stop = function(){
				return + new Date - this.startTime;
			};
			
			var colors = Highcharts.getOptions().colors;
			var categories = [];

			for (var i = 0; i < testList.length; i ++) {
				categories.push(testList[i].name);
			}

			var chart = new Highcharts.Chart({
				chart: {
					renderTo: 'container',
					height: categories.length * 40,
					type: 'bar'
				},

				title: {
					text: 'JavaScript 模板引擎负荷测试'
				},

				subtitle: {
					text: length + ' 条数据 × ' + number + ' 次渲染'
				},
						
				xAxis: {
					categories: categories,
					labels: {
						align: 'right',
						style: {
							fontSize: '12px',
							fontFamily: 'Verdana, sans-serif'
						}
					}
				},

				yAxis: {
					min: 0,
					title: {
						text: '耗时(毫秒)'
					}
				},

				legend: {
					enabled: false
				},

				tooltip: {
					formatter: function() {
						return '<b>'+ this.x +'</b><br/>'+
							this.y + '毫秒';
					}

				},

				credits: {
					enabled: false
				},
				plotOptions: {
					bar: {
						dataLabels: {
							enabled: true,
							formatter: function () {
								return this.y + 'ms';
							}
						}
					}
				},
				series: [{
					data : []
				}]

			});
			
			var log = function (message) {
				document.getElementById('log').innerHTML = message;
			};
			
			var tester = function (target) {
			
				
				var time = new Timer;
				target.tester();
				var endTime = time.stop();
				
				chart.series[0].addPoint({
					color: colors.shift(),
					y: endTime
				});
				
				
				if (!testList.length) {
					log('测试已完成，请不要迷恋速度');
					return;
				}

				target = testList.shift();
				
				log('正在测试: ' + target.name + '..');
				
				setTimeout(function () {
					tester(target);
				}, 500);
				
			};
			
			var target = testList.shift();
			log('正在测试: ' + target.name + '..');
			tester(target);

		};
		</script>





		<!-- tileTemplate 的模板 -->
		<script id="tile-test-template" type="text/tileTemplate">
		<ul>
			<% for (i = 0, l = list.length; i < l; i ++) { %>
				<li>用户: <%=list[i].user%>/ 网站：<%=list[i].site%></li>
			<% } %>
		</ul>
		</script>

        <!-- 貌似发现一个令人尴尬的事 by:pandao 2014-12-09 23:57:14 -->

		<!-- artTemplate 的模板 -->
		<script id="template" type="text/tmpl">
		<ul>
			<% for (i = 0, l = list.length; i < l; i ++) { %>
				<li>用户: <%=#list[i].user%>/ 网站：<%=#list[i].site%></li>
			<% } %>
		</ul>
		</script>

		<!-- baidu-template 的模板 -->
		<script id="baidu-template" type="text/tmpl">
		<ul>
			<% for (var val, i = 0, l = list.length; i < l; i ++) { %>
				<% val = list[i]; %>
				<li>用户: <%=val.user%>/ 网站：<%=val.site%></li>
			<% } %>
		</ul>
		</script>

		<!-- easyTemplate 的模板 -->
		<script id="easyTemplate" type="text/tmpl">
		<ul>
			<#list data.list as item>
				<li>用户: ${item.user}/ 网站：${item.site}</li>
			</#list>
		</ul>
		</script>

		<!-- tmpl 的模板 -->
		<script id="tmpl" type="text/tmpl">
		<ul>
			<% for (var val, i = 0, l = list.length; i < l; i ++) { %>
				<% val = list[i]; %>
				<li>用户: <%=val.user%>/ 网站：<%=val.site%></li>
			<% } %>
		</ul>
		</script>

		<!-- jqueryTmpl 的模板 -->
		<script id="jqueryTmpl" type="text/tmpl">
		<ul>
			{{each list}}
				<li>用户: ${$value.user}/ 网站：${$value.site}</li>
			{{/each}}
		</ul>
		</script>

		<!--juicer 的模板 -->
		<script id="juicer" type="text/tmpl">
		<ul>
			{@each list as val}
				<li>用户: $${val.user}/ 网站：$${val.site}</li>
			{@/each}
		</ul>
		</script>

		<!--etpl 的模板 -->
		<script id="etpl" type="text/tmpl">
		<ul>
			<!--for: ${list} as ${val} -->
				<li>用户: ${val.user}/ 网站：${val.site}</li>
			<!--/for-->
		</ul>
		</script>

		<!-- doT 的模板 -->
		<script id="doT" type="text/tmpl">
		<ul>
			{{ for (var val, i = 0, l = it.list.length; i < l; i ++) { }}
				{{ val = it.list; }}
				<li>用户: {{=val[i].user}}/ 网站：{{=val[i].site}}</li>
			{{ } }}
		</ul>
		</script>

		<!--Mustache 的模板 -->
		<script id="Mustache" type="text/tmpl">
		<ul>
			{{#list}}
				<li>用户: {{{user}}}/ 网站：{{{site}}}</li>
			{{/list}}
		</ul>
		</script>

		<!--Handlebars  的模板 -->
		<script id="Handlebars" type="text/tmpl">
		<ul>
			{{#list}}
				<li>用户: {{{user}}}/ 网站：{{{site}}}</li>
			{{/list}}
		</ul>
		</script>

		<!--kissy 的模板 -->
		<script id="kissy" type="text/tmpl">
		<ul>
			{{#each list as val}}
				<li>用户: {{val.user}}/ 网站：{{val.site}}</li>
			{{/each}}
		</ul>
		</script>


		<!-- ejs 的模板 -->
		<script id="ejs" type="text/tmpl">
		<ul>
		  <& for (var val, i = 0, l = @list.length; i < l; i ++) { &>
				<& val = @list[i]; &>
				<li>用户: <&= val.user &>； 网站：<&= val.site &></li> 
		  <& } &>
		</ul>
		</script>

		<!-- underscore 的模板 -->
		<script id="underscoreTemplate" type="text/tmpl">
		<ul>
			<% for (var i = 0, l = list.length; i < l; i ++) { %>
				<li>用户: <%=list[i].user%>/ 网站：<%=list[i].site%></li>
			<% } %>
		</ul>
		</script>
	</head>

	<body>
		<h1>引擎渲染速度测试</h1>
		<p style="color:red;">特别说明：为了能直观有效的进行“比较”，本测试用例使用的是 <a href="https://github.com/aui/artTemplate/tree/master/test">artTemplate</a> 的测试用例，感谢artTemplate的启发和工作。</p>
		<p><strong><script>document.write(length)</script></strong> 条数据 × <strong><script>document.write(number)</script></strong> 次渲染测试 </p>
		<p>tileTemplate [debug:false, filter:false, cached:true]</p>
		<p>artTemplate  [escape:false, cache:true]</p>
		<p><em>建议在拥有 v8 javascript 引擎的 chrome 浏览器上进行测试，避免浏览器停止响应</em></p>
		<p><button id="button-test" onclick="this.disabled=true;startTest()" style="padding: 5px;">开始测试&raquo;</button> <span id="log" style="font-size:12px"><script>for (var i = 0; i < testList.length; i ++) {document.write(testList[i].name + '; ')}</script></span></p>
		<div id="container" style="min-width: 400px; margin: 0 auto"></div>
	</body>
</html>